﻿#include "SideDisplayFrame.h"
#include "SideDisplayFrame.h"
#include "SideDisplayFrame.h"
#include "SideDisplayFrame.h"
#include "ui_SideDisplayFrame.h"


SideDisplayFrame::SideDisplayFrame(QWidget* parent)
	:QWidget(parent)
	,m_ui(new Ui::Form)
{
	m_ui->setupUi(this);


	//初始化模型：
	m_model = new QStandardItemModel(this);


	init();
}

SideDisplayFrame::~SideDisplayFrame()
{
	delete m_ui;
}


int SideDisplayFrame::fieldnameColumn(const QString& field)
{
	auto index = m_fieldnames.indexOf(field);
	if (-1 == index)
	{
		qWarning() << "fieldname field >" << field << "is not exists";
	}

	return index;
}


void SideDisplayFrame::init()
{
	//设置视图的模型：
	m_ui->displayTab->setModel(m_model);
	m_ui->displayTab->verticalHeader()->setVisible(false);									//列数不显示
	m_ui->displayTab->setEditTriggers(QTableView::NoEditTriggers);								//禁止编辑
	m_ui->displayTab->setSelectionMode(QTableView::SelectionMode::ContiguousSelection);			//设置行选择
	m_ui->displayTab->setSelectionMode(QAbstractItemView::NoSelection);					//设置不可选中
	m_ui->displayTab->setFocusPolicy(Qt::NoFocus);										//取消焦点
	m_ui->displayTab->setMouseTracking(true);												//设置鼠标追踪


	connect(m_ui->searchEdit, &QLineEdit::returnPressed, this, &SideDisplayFrame::ResponseSearch);
	connect(m_ui->searchEdit, &QLineEdit::textChanged, this, [=](const QString& text)
		{
			if (text.isEmpty())
			{
				ResponseSearch();
			}
		});
	connect(m_ui->searchBtn, &QPushButton::clicked, this, &SideDisplayFrame::ResponseSearch);


	connect(m_ui->enableBtn, &QPushButton::clicked, this, &SideDisplayFrame::onEnable);
	connect(m_ui->forbiddenBtn, &QPushButton::clicked, this, &SideDisplayFrame::onDisable);
	connect(m_ui->deleteBtn, &QPushButton::clicked, this, &SideDisplayFrame::onDelete);




	//设置表格的头视图：
	auto headerview = new SHeaderView(Qt::Orientation::Horizontal);
	m_ui->displayTab->setHorizontalHeader(headerview);


	//添加水平表头：
	FieldnameTranslate::instance()->addTranslate("user/user_id", "用户id");
	FieldnameTranslate::instance()->addTranslate("user/username", "用户名");
	FieldnameTranslate::instance()->addTranslate("user/gender", "性别");
	FieldnameTranslate::instance()->addTranslate("user/mobile", "电话");
	FieldnameTranslate::instance()->addTranslate("user/email", "邮箱");
	FieldnameTranslate::instance()->addTranslate("user/isEnable", "账号状态");
	FieldnameTranslate::instance()->addTranslate("user/controls", "操作");




	//视图页数情况显示：
	{
		auto layout = dynamic_cast<QVBoxLayout*>(m_ui->deleteBtn->parentWidget()->parentWidget()->layout());		//下行转换
		if(layout)
		{
			auto hlayout = new QHBoxLayout;
			hlayout->addStretch();
			pre_PageBtn = new QPushButton("上一页");
			hlayout->addWidget(pre_PageBtn);
			cur_PageLab = new QLabel("当前页数");
			cur_PageLab->setStyleSheet("background-color:white;color:black");
			hlayout->addWidget(cur_PageLab);
			next_PageBtn = new QPushButton("下一页");
			hlayout->addWidget(next_PageBtn);

			layout->insertLayout(layout->count() - 2, hlayout);
		}
	}

	//在批量按钮的布局中添加一些其他widget:
	{
		//获取按钮组的widget，转换成垂直布局对象，使用下行转换：
		auto batch_delete_button_layout = dynamic_cast<QHBoxLayout*>(m_ui->deleteBtn->parentWidget()->layout());		//下行转换
		if (batch_delete_button_layout)
		{
			//添加批量删除按钮：
			//batch_delete_button_layout->insertWidget(batch_delete_button_layout->count() - 1, new SSwitchButton);

			//添加	添加用户按钮：
			//batch_delete_button_layout->insertWidget(batch_delete_button_layout->count() - 1, new QLabel("\t\t"));		//先用这个来实现下占位
			m_addUserBtn = new QPushButton("添加用户");
			batch_delete_button_layout->insertWidget(batch_delete_button_layout->count(), m_addUserBtn);
		}
	}


	//弃用：
	connect(m_model, &QStandardItemModel::itemChanged, [=](QStandardItem* item)
		{
			//弃用：
			return;


			qDebug() << item->checkState();
			switch (item->checkState())
			{
			case Qt::Unchecked:
			{
				//统计未被选中的个数：
				int total = 0;
				for (int i = 0; i < m_model->rowCount(); i++)
				{
					if (m_model->item(i, 0)->checkState())
					{
						total++;
					}
				}

				//如果统计数大于0，就表示有项被选中，设置表格的头视图为半选择状态：
				if (total > 0)
				{
					headerview->setState(Qt::PartiallyChecked);			//半选择状态
				}
				//如果统计数等于0，就表示没有项被选中，设置表格的头视图为未选择状态：
				else
				{
					headerview->setState(Qt::Unchecked);
				}
			}
				break;
			case Qt::Checked:
			{
				int total = 0;
				//开始统计被选中的个数：
				for (int i = 0; i < m_model->rowCount(); i++)
				{
					if (m_model->item(i, 0)->checkState())
					{
						total++;
					}
				}

				//如果统计数等于模型的数据总数，就表示项全被选中，设置表格的头视图为选择状态：
				if (total == m_model->rowCount())
				{
					headerview->setState(Qt::Checked);
				}			
				//如果统计数不等于模型的数据总数，就表示项并不是都全被选中，设置表格的头视图为半选择状态：
				else
				{
					headerview->setState(Qt::PartiallyChecked);
				}
			}
			break;
			default:
				break;
			}
		});


	//代理：
	delegateinit(headerview);


	//搜索用户列表：
	ResponseSearch();


	//添加用户的菜单初始化：
	Menuinit();

}

void SideDisplayFrame::delegateinit(SHeaderView* headerview)
{
	//item复选框代理：
	auto checkdelegate = new CheckDelegate(m_ui->displayTab);
	m_ui->displayTab->setItemDelegateForColumn(0, checkdelegate);				//给第0列的复选框添加代理
			//表格的头视图的信号槽触发，全选或者全不选：
	connect(headerview, &SHeaderView::stateChanged, [=](int state)
		{
			//遍历视图的每行。并设置数据和数据类型：
			for (int i = 0; i < m_model->rowCount(); i++)
			{
				auto item = m_model->item(i, 0);
				item->setData(state, Qt::UserRole);
			}

			//如果state有效，就把模型的所有行数给到代理：
			if (state)
			{
				checkdelegate->setCheckCount(m_model->rowCount());
			}
			//无效，则把0给到代理：
			else
			{
				checkdelegate->setCheckCount(0);
			}
		});
			//item代理的信号槽触发，收到CheckDelegate的信号stateChanged后，则对应设置表格的头视图的状态：
	connect(checkdelegate, &CheckDelegate::stateChanged, [=]()
		{
			//获取代理的选中的个数：
			size_t cnt = checkdelegate->CheckCount();
			//如果等于模型的总行数，则设置表格的头视图为全选状态：
			if (cnt == m_model->rowCount())
			{
				headerview->setState(Qt::Checked);
			}
			//如果大于0，则表明有项被选择，但是并非全部，则设置表格的头视图为半选状态：
			else if (cnt > 0)
			{
				headerview->setState(Qt::PartiallyChecked);
			}
			//如果等于0，则表示没有项被选中，则设置表格的头视图为非选状态：
			else
			{
				headerview->setState(Qt::Unchecked);
			}
		});


	//Url代理：
	auto urldelegate = new UrlDelegate(m_ui->displayTab);
	m_ui->displayTab->setItemDelegateForColumn(fieldnameColumn("user_id"), urldelegate);				//给第1行的用户id添加代理
			//点击用户id，通过代理获取点击的行数和列数：
	connect(urldelegate, &UrlDelegate::requestOpenUrl, this, [=](const QModelIndex& index)
		{
			qDebug() << index;

			if (!m_userdetailshow)
			{
				m_userdetailshow = new UserDetailShowDlg;

				//在用户数据细节展示中数据改变了：
				connect(m_userdetailshow, &UserDetailShowDlg::userDataChanged, [=](const QJsonObject& object)
					{
						//这些代码多多少少有些问题：
#if 0
						m_model->item(index.row(), fieldnameColumn("user_id"))->setText(object.value("user_id").toString());
						m_model->item(index.row(), fieldnameColumn("username"))->setText(object.value("username").toString());
						int gender = object.value("gender").toInt();
						m_model->item(index.row(), fieldnameColumn("gender"))->setText(gender ? (gender == 1 ? "男" : "女") : "未知");
						m_model->item(index.row(), fieldnameColumn("isEnable"))->setData(object.value("isEnable").toBool(),Qt::UserRole);
						m_model->item(index.row(), fieldnameColumn("mobile"))->setText(object.value("mobile").toString());
						m_model->item(index.row(), fieldnameColumn("email"))->setText(object.value("email").toString());
#else
						//那就直接再查找一次：
						ResponseSearch();
#endif
					});
				//在用户数据细节展示中数据删除了：
				connect(m_userdetailshow, &UserDetailShowDlg::userDataDeleted, [=](const QJsonObject& deluser)
					{
						//在模型数据中（通过遍历用户id）来寻找被删除的用户：
						auto find_items = m_model->findItems(deluser.value("user_id").toString(),
																					Qt::MatchFlag::MatchFixedString,	//查找的匹配规则：固定的字符串，即必须字符串完全比配
																					fieldnameColumn("user_id"));
						if (!find_items.isEmpty())
						{
							auto find_deluser_row = find_items.first()->row();
							qDebug() << find_deluser_row;

							//在模型中删除被删除的用户的数据的行：
							m_model->removeRow(find_deluser_row);
						}
					});
			}


			QJsonObject juser;
			juser.insert("user_id", m_model->item(index.row(), fieldnameColumn("user_id"))->text());
			juser.insert("username", m_model->item(index.row(), fieldnameColumn("username"))->text());
			juser.insert("gender", m_model->item(index.row(), fieldnameColumn("gender"))->text());
			juser.insert("isEnable", m_model->item(index.row(), fieldnameColumn("isEnable"))->data(Qt::UserRole).toInt());
			juser.insert("mobile", m_model->item(index.row(), fieldnameColumn("mobile"))->text());
			juser.insert("email", m_model->item(index.row(), fieldnameColumn("email"))->text());
			juser.insert("password", m_userpassword.value(m_model->item(index.row(), fieldnameColumn("user_id"))->text()));

			m_userdetailshow->setUserData(juser);
			//_userdetailshow->show();
			MaskWidget::instance()->popup(m_userdetailshow);
		});


	//用户状态代理，实现开关设置用户状态：
	auto enableswitchdelegate = new EnableSwitchDelegate(m_ui->displayTab);
	m_ui->displayTab->setItemDelegateForColumn(fieldnameColumn("isEnable"), enableswitchdelegate);
			//点击使能开关，通过代理获取点击后（更新后）的状态和点击下标：
	connect(enableswitchdelegate, &EnableSwitchDelegate::enableswdeleData, this, [=](bool enable, const QModelIndex& index)
		{
			qDebug() << enable << index;

			auto user_id = m_model->item(index.row(), fieldnameColumn("user_id"))->text();

			//1.使用modify api来处理：
#if 0

			//该api中既有query 又有body，而在用SHttpClient发送数据时，是不能同时发送这两种数据的，所以query放在了网址上来实现使用该api。这个方法不太推荐

			SHttpClient(QUrl("http://" + sApp->globalConfig()->value("host/host").toString() + QString("/api/user/modify?user_id=") + user_id))
				.debug(true)
					.header("Authorization", "Bearer" + sApp->userData("user/token").toString())
						.json({ {"isEnable",enable}})
							.fail([](const QString& msg,int code)
								{
									qDebug() << msg << code;
								})
								.success([=](const QByteArray& array)
									{
										QJsonParseError error;
										auto jdocument = QJsonDocument::fromJson(array, &error);

										if (error.error == QJsonParseError::NoError)
										{
											return;
										}

										if (jdocument["code"].toInt() < 1000)
										{
											//修改状态成功；
											qDebug() << "success";
										}

									})
									.post();

#else
			//2.使用batch_modify api来处理：
			QJsonObject jobject;
			QJsonArray array;

			QJsonObject conditionObject = { {"user_id",user_id} };
			QJsonObject updateObject = { {"isEnable",enable} };
			QJsonObject resultObject;
			resultObject.insert("condition", conditionObject);
			resultObject.insert("update", updateObject);
			array.append(resultObject);
			jobject.insert("lists", array);

			SHttpClient(QUrl("http://" + sApp->globalConfig()->value("host/host").toString() + QString("/api/user/batch_modify")))
				.debug(true)
					.header("Authorization", "Bearer" + sApp->userData("user/token").toString())
						.json(jobject)
							.fail([](const QString& msg, int code)
								{
									qDebug() << msg << code;
								})
								.success([=](const QByteArray& array)
									{
										QJsonParseError error;
										auto jdocument = QJsonDocument::fromJson(array, &error);

										if (error.error != QJsonParseError::NoError)
										{
											return;
										}

										if (jdocument["code"].toInt() < 1000)
										{
											//修改成功：
										}
									})
									.post();
#endif

		});
	
	
	//新增一列操作代理：
	auto controlsdelegate = new ButtonDelegate(m_ui->displayTab);
	m_ui->displayTab->setItemDelegateForColumn(fieldnameColumn("controls"), controlsdelegate);
			//添加按钮：
	auto deleteButton = controlsdelegate->addButton(new QPushButton("删除"));
	//auto moreButton = controlsdelegate->addButton(new QPushButton("更多"));
			//设置按钮样式表：
	QString styleStr = R"(QPushButton{border-radius:3px;background-color:rgb(97,162,243);color:white};
								  QPushButton:hover {background-color:red; })";
	deleteButton->setStyleSheet(styleStr);
	deleteButton->setFixedSize(45, 20);
	//moreButton->setStyleSheet(styleStr);
	//moreButton->setFixedSize(45, 20);
			//添加复选框：
	//controlsdelegate->addButton(new QCheckBox)->setFixedSize(25, 20);
			//点击操作列的某个项，通过代理获取点击后的id和下标：
	connect(controlsdelegate, &ButtonDelegate::buttonCilcked, this, [=](int id, const QModelIndex& index)
		{
			qDebug() << id << index;


			//删除用户：
			if (0 == id)
			{
				//弹窗提示：
				if (QMessageBox::Cancel == QMessageBox::question(this, QObject::tr("tip~~~"), "你真要删除？", QMessageBox::Yes, QMessageBox::Cancel))
				{
					return;
				}


				auto user_id = m_model->item(index.row(), fieldnameColumn("user_id"))->text();
				qDebug() << user_id;

				QJsonArray array;
				array.append(user_id);

				SHttpClient(QUrl("http://" + sApp->globalConfig()->value("host/host").toString() + QString("/api/user/delete")))
					.debug(true)
						.header("Authorization", "Bearer" + sApp->userData("user/token").toString())
							.json({ {"user_id_lists",array}})
								.fail([](const QString& msg, int code)
									{
										qDebug() << msg << code;
									})
									.success([=](const QByteArray& array)
										{
											QJsonParseError error;

											auto jdocument =  QJsonDocument::fromJson(array, &error);
											if (error.error != QJsonParseError::NoError)
											{
												return;
											}

											if (jdocument["code"].toInt() < 1000)
											{
												//删除成功：
												m_model->removeRow(index.row());		//更新模型数据，去掉被删除的行；
											}
											else
											{
												//删除失败:
											}
										})
										.post();

			}
		});
}

void SideDisplayFrame::ResponseSearch()
{
	QVariantMap params;

	//设置param，如果账户是被禁用的，就不显示：
	//params.insert("isEnable", true);

	//获取搜索框的文本，如果文本不为空，就插入map中：
	auto query = m_ui->searchEdit->text();
	if (!query.isEmpty())
	{
		params.insert("query", query);
	}


	SHttpClient(QUrl("http://" + sApp->globalConfig()->value("host/host").toString() + QString("/api/user/list")))
		.debug(true)
			.header("Authorization", "Bearer" + sApp->userData("user/token").toString())
				.params(params)
					.success([=](const QByteArray& array)
						{
							QJsonParseError error;
							auto jdocument = QJsonDocument::fromJson(array, &error);
							if (error.error != QJsonParseError::NoError)
							{
								return;
							}


							//解析json数据;
							parseJson(jdocument.object());
						})
							.get();

}

void SideDisplayFrame::setBatchEnable(bool isEn)
{
	QJsonObject jobject;
	QJsonArray jArray;
	for (int i = 0; i < m_model->rowCount(); i++)
	{
		//获取项：
		auto item = m_model->item(i);
		//要判断这个项是否存在，并且：
		if (item && item->data(Qt::UserRole).toBool())
		{
			//如果bool类型不相同	再上传服务器，要求更新数据库，	这样会提高工作速度；
			if (m_model->item(i, fieldnameColumn("isEnable"))->data(Qt::UserRole).toInt() != isEn)
			{
				QJsonObject recordObject;
				QJsonObject conditionObject{ {"user_id",m_model->item(i, fieldnameColumn("user_id"))->text()}};
				QJsonObject updateObject{ {"isEnable",isEn} };
				recordObject.insert("condition", conditionObject);
				recordObject.insert("update", updateObject);

				jArray.append(recordObject);

				//直接更新模型数据:
				m_model->item(i, fieldnameColumn("isEnable"))->setData(isEn, Qt::UserRole);
			}
		}
	}
	jobject.insert("lists", jArray);


	SHttpClient(QUrl("http://" + sApp->globalConfig()->value("host/host").toString() + QString("/api/user/batch_modify")))
		.debug(true)
			.header("Authorization", "Bearer" + sApp->userData("user/token").toString())
				.json(jobject)
					.fail([](const QString& msg, int code)
						{
							qDebug() << msg << code;
						})
						.success([](const QByteArray& array)
							{
								QJsonParseError error;
								auto jdocument = QJsonDocument::fromJson(array, &error);
								if (error.error != QJsonParseError::NoError)
								{
									return;
								}
							})
							.post();

}

void SideDisplayFrame::onEnable()
{
	setBatchEnable(true);
}

void SideDisplayFrame::onDisable()
{
	setBatchEnable(false);
}

void SideDisplayFrame::onDelete()
{
	QJsonObject jobject;
	QJsonArray jArray;
	std::set<int, std::greater<int>> deleteRowsSets;		//设置一个容器，用来装要删除的行号，用倒序来排序；

	for (int i = 0; i < m_model->rowCount(); i++)
	{
		//获取项：
		auto item = m_model->item(i);
		//要判断这个项是否存在，并且被选中：
		if (item && item->data(Qt::UserRole).toBool())
		{
			//删除只需要知道用户的id就能执行了，所以直接把user_id传给服务器就行了：
			jArray.append(m_model->item(i,fieldnameColumn("user_id"))->text());

			deleteRowsSets.insert(i);
		}
	}
	jobject.insert("user_id_lists", jArray);


	SHttpClient(QUrl("http://" + sApp->globalConfig()->value("host/host").toString() + QString("/api/user/delete")))
		.debug(true)
			.header("Authorization", "Bearer" + sApp->userData("user/token").toString())
				.json(jobject)
					.fail([](const QString& msg, int code)
						{
							qDebug() << msg << code;
						})
						.success([=](const QByteArray& array)
							{
								for (auto row : deleteRowsSets)
								{
									/*
										删除成功后，如果是顺序的去除模型的数据，会出现问题，这主要是因为模型的数据之间可能存在相互依赖或者关联。
										如果不按照正确的顺序删除这些数据，就有可能导致数据不一致或者程序出现错误。
										举个例子，假设有一个包含订单和订单详情的数据库模型。订单详情表中的记录与订单表中的记录是关联的，
										也就是说订单详情依赖于订单。如果你先删除订单表中的记录，而不考虑订单详情表中的记录，就会导致订单详情表中的
										数据变得无效或者出现错误。这样就会导致数据不一致的问题。
										在程序中，类似的情况也会发生。如果你在处理模型数据时不按照正确的顺序进行操作，就有可能导致程序出现错误或者
										数据不一致的情况。
										因此，为了避免这些问题，我们应该按照正确的顺序处理模型的数据，特别是在删除数据时。通常情况下，我们会
										先删除依赖关系较弱的数据，然后再删除依赖关系较强的数据，以确保数据的完整性和一致性。
									*/
									m_model->removeRow(row);
								}
							})
							.post();

}

//解析数据：
void SideDisplayFrame::parseJson(const QJsonObject& object)
{
	//先清空：
	m_model->clear();


	//设置水平表头的文本：
			//共有三种方法：
#if 1

	#if 0
		QStringList columnName = {"用户id","用户名","性别","电话","邮箱","账号状态"};
		m_model->setHorizontalHeaderLabels(columnName);
	#else
		for (int i = 0; i < m_fieldnames.size(); i++)
		{
			//设置水平表头：
			m_model->setHorizontalHeaderItem(i,new QStandardItem( FieldnameTranslate::instance()->translate("user", m_fieldnames.at(i))));
		}
	#endif

#else
	auto item = new QStandardItem("");
	m_model->setHorizontalHeaderItem(0, item);
	item = new QStandardItem("用户id");
//	item->setData(QColor(Qt::black), Qt::ForegroundRole);
	m_model->setHorizontalHeaderItem(1, item);
	item = new QStandardItem("用户名");
//	item->setData(QColor(Qt::black), Qt::ForegroundRole);
	m_model->setHorizontalHeaderItem(2, item);
	item = new QStandardItem("性别");
//	item->setData(QColor(Qt::black), Qt::ForegroundRole);
	m_model->setHorizontalHeaderItem(3, item);
	item = new QStandardItem("电话");
//	item->setData(QColor(Qt::black), Qt::ForegroundRole);
	m_model->setHorizontalHeaderItem(4, item);
	item = new QStandardItem("邮箱");
//	item->setData(QColor(Qt::black), Qt::ForegroundRole);
	m_model->setHorizontalHeaderItem(5, item);
	item = new QStandardItem("账号状态");
//	item->setData(QColor(Qt::black), Qt::ForegroundRole);
	m_model->setHorizontalHeaderItem(6, item);
#endif


	//设置视图的水平表头的背景：
	m_ui->displayTab->horizontalHeader()->setStyleSheet("QHeaderView::section{background-color:rgb(66,66,66)}");




	//获取数据表中的数据数组:
	auto dataArray = object.value("data").toObject().value("lists").toArray();
	for (int i = 0; i < dataArray.size(); i++)
	{
		//项列表：
		QList<QStandardItem*> itemsList;


		//获取数据数组的Object对象：
		auto juser = dataArray.at(i).toObject();


		//把数据表中的内容显示到视图中
				//性别和是否被禁用需要单独获取：
		auto gender = juser.value("gender").toInteger();
		auto isEnable = juser.value("isEnable").toInt();


		//保存用户的密码：
		m_userpassword.insert(juser.value("user_id").toString(), juser.value("password").toString());


				//项：
						//两种方法都可以：
#if 0
		QStandardItem* items = nullptr;

						//复选框：
		items = new QStandardItem;
		//items->setCheckable(true);
		itemsList.append(items);
						//用户id：
		items = new QStandardItem(juser.value("user_id").toVariant().toString());
		items->setTextAlignment(Qt::AlignCenter);			//设置居中对齐
		itemsList.append(items);
						//用户名：
		items = new QStandardItem(juser.value("username").toVariant().toString());
		items->setTextAlignment(Qt::AlignCenter);			//设置居中对齐
		itemsList.append(items);
						//性别：
		items = new QStandardItem(gender == 0 ? "未知" : (gender == 1 ? "男" : "女"));
		items->setTextAlignment(Qt::AlignCenter);			//设置居中对齐
		itemsList.append(items);
						//电话：
		items = new QStandardItem(juser.value("mobile").toVariant().toString());
		items->setTextAlignment(Qt::AlignCenter);			//设置居中对齐
		itemsList.append(items);
						//邮箱：
		items = new QStandardItem(juser.value("email").toVariant().toString());
		items->setTextAlignment(Qt::AlignCenter);			//设置居中对齐
		itemsList.append(items);			
						//账号状态：
		QString fontcolor = (isEnable ? "正常" : "禁用");
		items = new QStandardItem(fontcolor);
		//必须要设置用户角色类型的数据，不然在批量那里识别不到：
		items->setData(isEnable, Qt::UserRole);
		//设置该项字体颜色：
		if (fontcolor.contains("正常"))
		{
			items->setData(QColor(Qt::green), Qt::ForegroundRole);
		}
		else
		{
			items->setData(QColor(Qt::red), Qt::ForegroundRole);
		}
		items->setTextAlignment(Qt::AlignCenter);			//设置居中对齐
		itemsList.append(items);
#else
		//	设置循环插入数据项，方便给每个项设置文本居中：
		for (const auto& fieldname : m_fieldnames)
		{
			auto item = new QStandardItem;

			if (fieldname == "gender")
			{
				item->setText(gender == 0 ? "未知" : (gender == 1 ? "男" : "女"));
			}
			else if (fieldname == "isEnable")
			{
				QString enable = isEnable ? "正常" : "禁用";
						//必须要设置用户角色类型的数据，不然在批量那里识别不到：
				item->setData(!!isEnable, Qt::UserRole);	//!! —— 转成bool类型

				//用户状态列被代理后，下面就没用了：
				item->setText(enable);
				//根据用户状态设置字体颜色，看的更直观：
				if (enable == "正常")
					item->setData(QColor(Qt::green), Qt::ForegroundRole);
				else
					item->setData(QColor(Qt::red), Qt::ForegroundRole);
			}
			else
			{
				item->setText(juser.value(fieldname).toVariant().toString());
			}
			item->setTextAlignment(Qt::AlignCenter);			//设置文本居中显示
			itemsList.append(item);
		}
#endif


		//把数据添加到模型中：
		m_model->appendRow(itemsList);
	}


	//查看QMap容器：
	//for (auto it = m_userpassword.begin(); it != m_userpassword.end(); ++it)
	//{
	//	qDebug() << it.key() << ":" << it.value();
	//}


	//设置列的宽度一定要在数据设置完之后再设置：
						//1.设置第一列的大小并且大小固定：
	m_ui->displayTab->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed);		//设置该水平表头的大小固定
	m_ui->displayTab->horizontalHeader()->resizeSection(0, 25);
						//2.设置其他列的大小随窗口拉伸：
	m_ui->displayTab->horizontalHeader()->setSectionResizeMode(1,QHeaderView::Stretch);
	m_ui->displayTab->horizontalHeader()->setSectionResizeMode(2,QHeaderView::Stretch);
	m_ui->displayTab->horizontalHeader()->setSectionResizeMode(3,QHeaderView::Stretch);
	m_ui->displayTab->horizontalHeader()->setSectionResizeMode(4,QHeaderView::Stretch);
	m_ui->displayTab->horizontalHeader()->setSectionResizeMode(5,QHeaderView::Stretch);
	m_ui->displayTab->horizontalHeader()->setSectionResizeMode(6,QHeaderView::Stretch);
	m_ui->displayTab->horizontalHeader()->setSectionResizeMode(7,QHeaderView::Stretch);


	//恢复复选框默认状态：				setState函数是SHeaderView类的函数，而m_ui->displayTab->horizontalHeader()是QTableView类的，这需要下行转换，保证数据的安全：
	dynamic_cast<SHeaderView*>(m_ui->displayTab->horizontalHeader())->setState(Qt::Unchecked);
}

QList<QStandardItem*> SideDisplayFrame::ItemsFromJsonObject(const QJsonObject& juser)
{
	QList<QStandardItem*>itemsList;


	//把数据表中的内容显示到视图中
				//性别和是否被禁用需要单独获取：
	auto gender = juser.value("gender").toInteger();
	auto isEnable = juser.value("isEnable").toInt();


	//项：
		//	设置循环插入数据项，方便给每个项设置文本居中：
	for (const auto& fieldname : m_fieldnames)
	{
		auto item = new QStandardItem;

		if (fieldname == "gender")
		{
			item->setText(gender == 0 ? "未知" : (gender == 1 ? "男" : "女"));
		}
		else if (fieldname == "isEnable")
		{
			QString enable = isEnable ? "正常" : "禁用";
			//必须要设置用户角色类型的数据，不然在批量那里识别不到：
			item->setData(!!isEnable, Qt::UserRole);	//!! —— 转成bool类型

			//用户状态列被代理后，下面就没用了：
			item->setText(enable);
			//根据用户状态设置字体颜色，看的更直观：
			if (enable == "正常")
				item->setData(QColor(Qt::green), Qt::ForegroundRole);
			else
				item->setData(QColor(Qt::red), Qt::ForegroundRole);
		}
		else
		{
			item->setText(juser.value(fieldname).toVariant().toString());
		}
		item->setTextAlignment(Qt::AlignCenter);			//设置文本居中显示
		itemsList.append(item);
	}

	return itemsList;
}

void SideDisplayFrame::Menuinit()
{
	m_importmenu = new QMenu(this);

	m_addUserBtn->setMenu(m_importmenu);

	m_importmenu->addAction("单条导入", this, &SideDisplayFrame::Single_Import);
	m_importmenu->addAction("批量导入", this, &SideDisplayFrame::Batch_Import);
}

void SideDisplayFrame::Single_Import()
{
	if (!m_useradddlg)
	{
		m_useradddlg = new UserAddDlg;

		connect(m_useradddlg, &UserAddDlg::userDataChanged, this, [=](const QJsonObject& user)
			{
				m_model->insertRow(m_model->rowCount(), ItemsFromJsonObject(user));
				m_useradddlg->close();
			});


		//m_useradddlg->show();
		MaskWidget::instance()->popup(m_useradddlg);


		//添加用户界面关闭后，发送信号，本窗口接受到该信号后，将添加用户界面的指针置空，方便下次再重新打开使用：
		connect(m_useradddlg, &UserAddDlg::endShow, this, [=]
			{
				m_useradddlg = nullptr;
			});
	}
}

void SideDisplayFrame::Batch_Import()
{
	//选择文件提示信息：
	QMessageBox::about(this, "tip~~~", "注意呦,选择文件的表格格式必须为:\n用户id、用户姓名、性别、电话号码、电子邮件、密码\n的格式哟");


	auto filename = QFileDialog::getOpenFileName(this, "选择用户数据格式", "./", "xlsx (*.xlsx;*.csv);;all (*.*)");
	if (filename.isEmpty())
	{
		qWarning() << "filename is null";
		return;
	}
	qDebug() << filename;


	//现在要判断是哪个类型的文件格式了：
	auto format = QFileInfo(filename).suffix();
	if (0 == format.compare("csv", Qt::CaseInsensitive))					//csv格式文件
	{
		parse_CSV_file(filename);
	}
	else if (0 == format.compare("xlsx", Qt::CaseInsensitive))			//xlsx格式文件
	{
		parse_XLSX_file(filename);
	}
}

void SideDisplayFrame::parse_CSV_file(const QString& filename)
{
	QFile file(filename);
	if (!file.open(QIODevice::ReadOnly))
	{
		qWarning() << filename << "open failed" << file.errorString();
		return;
	}


	//文件流来操作数据：
	QTextStream stream(&file);

	//检测文件的字节顺序标记（Byte Order Mark，BOM）并设置相应的编码方式:
	auto guessBom = file.read(3);		//读前三个字节；
	if (guessBom.startsWith("\xEF\xBB\xBf"))			//"\xEF\xBB\xBF"——这个序列是 UTF-8 编码的 BOM。如果是，就将 stream 对象的编码设置为 UTF-8
	{
		stream.setEncoding(QStringConverter::Utf8);
	}
	else
	{
		//否则，将编码设置为系统默认的编码方式:
		stream.setEncoding(QStringConverter::System);
	}
	qDebug() << guessBom;

	//读取表格的第一行：水平表头的标题
	auto headertitles = stream.readLine().split(',');			//csv格式文件的表格 用记事本方式打开会发现，是用逗号来实行文本断开的
	/*
		用户id,用户姓名,性别,手机号码,电子邮件,密码
	*/
	qDebug() << headertitles;

	//读取表格用户数据：
	QJsonArray jArray;
	while (!stream.atEnd())
	{
		auto line_data = stream.readLine().split(',');
		if (6 != line_data.size())
		{
			qWarning() << "表头字段数量不够，导入失败";
			break;
		}

		QJsonObject jobject;
		jobject.insert("user_id", line_data.at(0));
		jobject.insert("username", line_data.at(1));
		int gender =( line_data.at(2) == "未知" ?		0	:	(line_data.at(2) == "男" ? 1 : 2)		);
		jobject.insert("gender", gender);
		jobject.insert("mobile", line_data.at(3));
		jobject.insert("email", line_data.at(4));
		jobject.insert("password", line_data.at(5));
		jArray.append(jobject);
	}


	SHttpClient(QUrl("http://" + sApp->globalConfig()->value("host/host").toString() + QString("/api/user/batch_create")))
		.debug(true)
			.header("Authorization", "Bearer" + sApp->userData("user/token").toString())
				.json({ {"lists",jArray}})
					.fail([](const QString& msg, int code)
						{
							qDebug() << msg << code;
						})
						.success([=](const QByteArray& array)
							{
								QJsonParseError error;
								auto jdocument = QJsonDocument::fromJson(array, &error);
								if (error.error != QJsonParseError::NoError && jdocument["code"].toInt() > 1000)
								{
									return;
								}
								else
								{
									ResponseSearch();
								}
							})
							.post();
}

void SideDisplayFrame::parse_XLSX_file(const QString& filename)
{
	using namespace QXlsx;

	Document doc(filename);
	if (!doc.load())
	{
		qWarning() << filename << "xlsx load filed";
		return;
	}


	//获取工作簿：
	Workbook* wbook = doc.workbook();
	qDebug() << "sheetCount >" << wbook->sheetCount();
	qDebug() << "sheetNames >" << doc.sheetNames();


	//获取工作表：
	Worksheet* sheet = doc.currentWorksheet();
	//获取单元格的范围:
	CellRange range = sheet->dimension();
	qDebug() << range.rowCount() << range.columnCount();

	/*
		用户id、用户姓名、性别、电话号码、电子邮件、密码
	*/
	QJsonArray jArray;
	for (int r = 2; r <= range.rowCount(); r++)
	{
		QJsonObject jObject;
		for (int c = 1; c <= range.columnCount(); c++)
		{
			Cell* cell = sheet->cellAt(r, c);
			if (cell)
			{
				//获取值：
				auto value = cell->value().toString();
				qDebug() << value;
				if (c == 1)
				{
					jObject.insert("user_id",value);
				}
				else if (c == 2)
				{
					jObject.insert("username",value);
				}
				else if (c == 3)
				{
					jObject.insert("gender",value == "未知" ? 0 : (value == "男" ? 1 : 0));
				}
				else if (c == 4)
				{
					jObject.insert("mobile", value);
				}
				else if (c == 5)
				{
					jObject.insert("email", value);
				}
				else if (c == 6)
				{
					jObject.insert("password", value);
				}
			}
		}
		jArray.append(jObject);
	}


	SHttpClient(QUrl("http://" + sApp->globalConfig()->value("host/host").toString() + QString("/api/user/batch_create")))
		.debug(true)
			.header("Authorization", "Bearer" + sApp->userData("user/token").toString())
				.json({ {"lists",jArray} })
					.fail([](const QString& msg, int code)
						{
							qDebug() << msg << code;
						})
						.success([=](const QByteArray& array)
							{
								QJsonParseError error;
								auto jdocument = QJsonDocument::fromJson(array, &error);
								if (error.error != QJsonParseError::NoError && jdocument["code"].toInt() > 1000)
								{
									return;
								}
								else
								{
									ResponseSearch();
								}
							})
							.post();
}
